﻿#ifndef BASEDATA_H
#define BASEDATA_H

#include "basedata.h"


namespace xvs {

class OBJLIB_EXPORT Point2DInt : public BaseData
{
    Q_OBJECT

    Q_PROPERTY(Integer* X READ X WRITE SetX)
    Q_PROPERTY(Integer* Y READ Y WRITE SetY)
public:
    DATA_COPY_TYPE(Point2DInt)

    Point2DInt();
    Point2DInt(Integer x,Integer y);
    Point2DInt(const Point2DInt& rhs)
    {
        *this = rhs;
    }

    Point2DInt& operator = (const Point2DInt& rhs);

public:
    Q_INVOKABLE Integer* X() { return &mx; }
    Q_INVOKABLE Integer* Y() { return &my; }

    Q_INVOKABLE void SetX(Integer* x) { mx = *x; }
    Q_INVOKABLE void SetY(Integer* y) { my = *y; }

private:

    Integer mx;
    Integer my;
};

using Location = Point2DInt;

class OBJLIB_EXPORT Point2D : public BaseData
{
    Q_OBJECT

    Q_PROPERTY(Real* X READ X WRITE SetX)
    Q_PROPERTY(Real* Y READ Y WRITE SetY)
public:
    DATA_COPY_TYPE(Point2D)

    Point2D();
    ~Point2D();

//    Point2D(float x, float y);
    Point2D(Real x, Real y);

    Point2D(const Point2D& rhs);

    Point2D& operator = (const Point2D& rhs);

public:
    Q_INVOKABLE Real* X();
    Q_INVOKABLE Real* Y();

    Q_INVOKABLE void SetX(Real* x);
    Q_INVOKABLE void SetY(Real* y);

public:
    Real mx;
    Real my;
};

class OBJLIB_EXPORT Point3D : public BaseData
{
    Q_OBJECT

    Q_PROPERTY(Real* X READ X WRITE SetX)
    Q_PROPERTY(Real* Y READ Y WRITE SetY)
    Q_PROPERTY(Real* Z READ Z WRITE SetZ)
public:
    DATA_COPY_TYPE(Point3D)

    Point3D();
//    Point3D(float x,float y,float z);
    Point3D(Real x,Real y,Real z);
    Point3D(const Point3D& rhs)
    {
        mx = rhs.mx;
        my = rhs.my;
        mz = rhs.mz;
    }

    Point3D& operator = (const Point3D& rhs);

public:
    Q_INVOKABLE Real* X() { return &mx; }
    Q_INVOKABLE Real* Y() { return &my; }
    Q_INVOKABLE Real* Z() { return &mz; }

    Q_INVOKABLE void SetX(const Real* x) { mx = *x; }
    Q_INVOKABLE void SetY(const Real* y) { my = *y; }
    Q_INVOKABLE void SetZ(const Real* z) { mz = *z; }

private:
    Real mx;
    Real my;
    Real mz;
};

class OBJLIB_EXPORT Circle2D : public BaseData
{
    Q_OBJECT

    Q_PROPERTY(Point2D* Center READ Center WRITE SetCenter)
    Q_PROPERTY(Real* Radius READ Radius WRITE SetRadius)
public:
    DATA_COPY_TYPE(Circle2D)

    Circle2D();
    ~Circle2D();
    Circle2D(Point2D center,Real radius);
    Circle2D(const Circle2D& rhs);

    Circle2D& operator = (const Circle2D& rhs);

public:
    Q_INVOKABLE Point2D* Center() { return &mCenter; }
    Q_INVOKABLE Real* Radius() { return &mRadius; }

    Q_INVOKABLE void SetCenter(Point2D* center) { mCenter = *center; }
    Q_INVOKABLE void SetRadius(const Real* radius) { mRadius = *radius; }

private:
    Point2D mCenter;
    Real mRadius;
};

class OBJLIB_EXPORT CircleFittingField : public BaseData
{
    Q_OBJECT

    Q_PROPERTY(Circle2D* Axis READ Axis WRITE SetAxis)
    Q_PROPERTY(Real* Width READ Width WRITE SetWidth)
public:
    DATA_COPY_TYPE(CircleFittingField)

    CircleFittingField();
    CircleFittingField(const Circle2D& axis,Real width);
    CircleFittingField(const CircleFittingField& rhs)
    {
        mAxis = rhs.mAxis;
        mWidth = rhs.mWidth;
    }

    CircleFittingField& operator = (const CircleFittingField& rhs);

public:
    Q_INVOKABLE Circle2D* Axis() { return &mAxis; }
    Q_INVOKABLE Real* Width() { return &mWidth; }

    Q_INVOKABLE void SetAxis(Circle2D* axis) { mAxis = *axis; }
    Q_INVOKABLE void SetWidth(const Real* width) { mWidth = *width; }

private:
    Circle2D mAxis;
    Real mWidth;
};

class OBJLIB_EXPORT Arc2D : public BaseData//圆弧
{
    Q_OBJECT

    Q_PROPERTY(Point2D* Center READ Center WRITE SetCenter)
    Q_PROPERTY(Real* Radius READ Radius WRITE SetRadius)
    Q_PROPERTY(Real* StartAngle READ StartAngle WRITE SetStartAngle)
    Q_PROPERTY(Real* SweepAngle READ SweepAngle WRITE SetSweepAngle)

public:
    DATA_COPY_TYPE(Arc2D)

    Arc2D();
    Arc2D(const Point2D& center,Real radius,Real startAngle,Real sweepAngle);
    Arc2D(const Arc2D& rhs)
    {
        mCenter = rhs.mCenter;
        mRadius = rhs.mRadius;
        mStartAngle = rhs.mStartAngle;
        mSweepAngle = rhs.mSweepAngle;
    }

    Arc2D& operator = (const Arc2D& rhs);

public:
    Q_INVOKABLE Point2D* Center() { return &mCenter; }
    Q_INVOKABLE Real* Radius() { return &mRadius; }
    Q_INVOKABLE Real* StartAngle() { return &mStartAngle; }
    Q_INVOKABLE Real* SweepAngle() { return &mSweepAngle; }

    Q_INVOKABLE void SetCenter(Point2D* center) { mCenter = *center; }
    Q_INVOKABLE void SetRadius(const Real* radius) { mRadius = *radius; }
    Q_INVOKABLE void SetStartAngle(const Real* startAngle) { mStartAngle = *startAngle; }
    Q_INVOKABLE void SetSweepAngle(const Real* sweepAngle) { mSweepAngle = *sweepAngle; }

private:
    Point2D mCenter;
    Real mRadius;
    Real mStartAngle;
    Real mSweepAngle;
};

class OBJLIB_EXPORT ArcFittingField : public BaseData//圆弧阈
{
    Q_OBJECT

    Q_PROPERTY(Arc2D* Axis READ Axis WRITE SetAxis)
    Q_PROPERTY(Real* Width READ Width WRITE SetWidth)
public:
    DATA_COPY_TYPE(ArcFittingField)

    ArcFittingField();
    ArcFittingField(const Arc2D& axis,float width);
    ArcFittingField(const ArcFittingField& rhs);

    ArcFittingField& operator = (const ArcFittingField& rhs);

public:
    Q_INVOKABLE Arc2D* Axis() { return &mAxis; }
    Q_INVOKABLE Real* Width() { return &mWidth; }

    Q_INVOKABLE void SetAxis(Arc2D* axis) { mAxis = *axis; }
    Q_INVOKABLE void SetWidth(const Real* width) { mWidth = *width; }

private:
    Arc2D mAxis;
    Real mWidth;
};

class OBJLIB_EXPORT Rectangle2D : public BaseData
{
    Q_OBJECT

    Q_PROPERTY(Point2D* Origin READ Origin WRITE SetOrigin)
    Q_PROPERTY(Real* Angle READ Angle WRITE SetAngle)
    Q_PROPERTY(Real* Width READ Width WRITE SetWidth)
    Q_PROPERTY(Real* Height READ Height WRITE SetHeight)
public:
    DATA_COPY_TYPE(Rectangle2D)

    Rectangle2D();
    Rectangle2D(const Point2D& origin,Real angle,Real width,Real height);
    Rectangle2D(const Rectangle2D& rhs);

    Rectangle2D& operator = (const Rectangle2D& rhs);

public:
    Q_INVOKABLE Point2D* Origin() { return &mOrigin; }
    Q_INVOKABLE Real* Angle() { return &mAngle; }
    Q_INVOKABLE Real* Width() { return &mWidth; }
    Q_INVOKABLE Real* Height() { return &mHeight; }

    Q_INVOKABLE void SetOrigin(Point2D* origin) { mOrigin = *origin; }
    Q_INVOKABLE void SetAngle(const Real* angle) { mAngle = *angle; }
    Q_INVOKABLE void SetWidth(const Real* width) { mWidth = *width; }
    Q_INVOKABLE void SetHeight(const Real* height) { mHeight = *height; }


private:
    Point2D mOrigin;
    Real mAngle;
    Real mWidth;
    Real mHeight;
};

class OBJLIB_EXPORT Rectangle2DInt : public BaseData
{
    Q_OBJECT

    Q_PROPERTY(Point2DInt* Origin READ Origin WRITE SetOrigin)
    Q_PROPERTY(Real* Angle READ Angle WRITE SetAngle)
    Q_PROPERTY(Integer* Width READ Width WRITE SetWidth)
    Q_PROPERTY(Integer* Height READ Height WRITE SetHeight)
public:
    DATA_COPY_TYPE(Rectangle2DInt)

    Rectangle2DInt();
    Rectangle2DInt(const Point2DInt& origin,Real angle,Integer width,Integer height);
    Rectangle2DInt(const Rectangle2DInt& rhs);
    Rectangle2DInt& operator = (const Rectangle2DInt& rhs);

public:
    Q_INVOKABLE Point2DInt* Origin() { return &mOrigin; }
    Q_INVOKABLE Real* Angle() { return &mAngle; }
    Q_INVOKABLE Integer* Width() { return &mWidth; }
    Q_INVOKABLE Integer* Height() { return &mHeight; }

    Q_INVOKABLE void SetOrigin(Point2DInt* origin) { mOrigin = *origin; }
    Q_INVOKABLE void SetAngle(const Real* angle) { mAngle = *angle; }
    Q_INVOKABLE void SetWidth(const Integer* width) { mWidth = *width; }
    Q_INVOKABLE void SetHeight(const Integer* height) { mHeight = *height; }

private:
    Point2DInt mOrigin;
    Real mAngle;
    Integer mWidth;
    Integer mHeight;
};

class OBJLIB_EXPORT Box2D : public BaseData
{
    Q_OBJECT

    Q_PROPERTY(Real* X READ X WRITE SetX)
    Q_PROPERTY(Real* Y READ Y WRITE SetY)
    Q_PROPERTY(Real* Width READ Width WRITE SetWidth)
    Q_PROPERTY(Real* Height READ Height WRITE SetHeight)
public:
    DATA_COPY_TYPE(Box2D)

    Box2D();
    Box2D(Real x,Real y,Real width,Real height);
    Box2D(const Box2D& rhs);

    Box2D& operator = (const Box2D& rhs);

public:
    Q_INVOKABLE Real* X() { return &mx; }
    Q_INVOKABLE Real* Y() { return &my; }
    Q_INVOKABLE Real* Width() { return &mWidth; }
    Q_INVOKABLE Real* Height() { return &mHeight; }

    Q_INVOKABLE void SetX(const Real* x) { mx = *x; }
    Q_INVOKABLE void SetY(const Real* y) { my = *y; }
    Q_INVOKABLE void SetWidth(const Real* width) { mWidth = *width; }
    Q_INVOKABLE void SetHeight(const Real* height) { mHeight = *height; }

private:
    Real mx;
    Real my;
    Real mWidth;
    Real mHeight;
};

class OBJLIB_EXPORT Box2DInt : public BaseData
{
    Q_OBJECT

    Q_PROPERTY(Integer* X READ X WRITE SetX)
    Q_PROPERTY(Integer* Y READ Y WRITE SetY)
    Q_PROPERTY(Integer* Width READ Width WRITE SetWidth)
    Q_PROPERTY(Integer* Height READ Height WRITE SetHeight)
public:
    DATA_COPY_TYPE(Box2DInt)

    Box2DInt();
    Box2DInt(Integer x,Integer y,Integer width,Integer height);
    Box2DInt(const Box2DInt& rhs);

    Box2DInt& operator = (const Box2DInt& rhs);

public:
    Q_INVOKABLE Integer* X() { return &mx; }
    Q_INVOKABLE Integer* Y() { return &my; }
    Q_INVOKABLE Integer* Width() { return &mWidth; }
    Q_INVOKABLE Integer* Height() { return &mHeight; }

    Q_INVOKABLE void SetX(const Integer* x) { mx = *x; }
    Q_INVOKABLE void SetY(const Integer* y) { my = *y; }
    Q_INVOKABLE void SetWidth(const Integer* width) { mWidth = *width; }
    Q_INVOKABLE void SetHeight(const Integer* height) { mHeight = *height; }

private:
    Integer mx;
    Integer my;
    Integer mWidth;
    Integer mHeight;
};

class OBJLIB_EXPORT EdgeTransitionType : public Enum
{
    Q_OBJECT
public:
    EdgeTransitionType()
    {
        AddEnumItem(0,"BrightToDark");// 由白到黑
        AddEnumItem(1,"DarkToBright");// 由黑到白
        AddEnumItem(2,"Any");         // 任意
        SetKey(0);
    }
};

//边缘点
class OBJLIB_EXPORT Edge1D : public BaseData
{
    Q_OBJECT

    Q_PROPERTY(Point2D* Point READ Point WRITE SetPoint)
    Q_PROPERTY(Real* Magnitude READ Magnitude WRITE SetMagnitude)
    Q_PROPERTY(EdgeTransitionType* Transition READ Transition WRITE SetTransition)
public:
    DATA_COPY_TYPE(Edge1D)

    Edge1D();
    Edge1D(const Point2D& point,Real magnitude,EdgeTransitionType transition);
    Edge1D(const Edge1D& rhs);

    Edge1D& operator = (const Edge1D& rhs);

public:
    Q_INVOKABLE Point2D* Point() { return &mPoint; }
    Q_INVOKABLE Real* Magnitude() { return &mMagnitude; }
    Q_INVOKABLE EdgeTransitionType* Transition() { return &mTransition; }

    Q_INVOKABLE void SetPoint(Point2D* point) { mPoint = *point; }
    Q_INVOKABLE void SetMagnitude(const Real* magnitude) { mMagnitude = *magnitude; }
    Q_INVOKABLE void SetTransition(const EdgeTransitionType* transition) { mTransition = *transition; }

private:
    Point2D mPoint;
    Real mMagnitude;//梯度幅值
    EdgeTransitionType mTransition;//方向
};

//边缘点之间的距离
class OBJLIB_EXPORT Gap1D : public BaseData
{
    Q_OBJECT

    Q_PROPERTY(Point2D* Point1 READ Point1 WRITE SetPoint1)
    Q_PROPERTY(Point2D* Point2 READ Point2 WRITE SetPoint2)
    Q_PROPERTY(Real* Width READ Width WRITE SetWidth)
public:
    DATA_COPY_TYPE(Gap1D)

    Gap1D();
    Gap1D(const Point2D& point1,const Point2D& point2,Real width);
    Gap1D(const Gap1D& rhs);

    Gap1D& operator = (const Gap1D& rhs);

public:
    Q_INVOKABLE Point2D* Point1() { return &mPoint1; }
    Q_INVOKABLE Point2D* Point2() { return &mPoint2; }
    Q_INVOKABLE Real* Width() { return &mWidth; }

    Q_INVOKABLE void SetPoint1(Point2D* point) { mPoint1 = *point; }
    Q_INVOKABLE void SetPoint2(Point2D* point) { mPoint2 = *point; }
    Q_INVOKABLE void SetWidth(const Real* width) { mWidth = *width; }

private:
    Point2D mPoint1;
    Point2D mPoint2;
    Real mWidth;
};

//直线ax + by + c = 0
class OBJLIB_EXPORT Line2D : public BaseData
{
    Q_OBJECT

    Q_PROPERTY(Real* A READ A WRITE SetA)
    Q_PROPERTY(Real* B READ B WRITE SetB)
    Q_PROPERTY(Real* C READ C WRITE SetC)
public:
    DATA_COPY_TYPE(Line2D)

    Line2D();
    Line2D(Real a,Real b,Real c);
    Line2D(const Line2D& rhs);

    Line2D& operator = (const Line2D& rhs);

public:
    Q_INVOKABLE Real* A() { return &mA; }
    Q_INVOKABLE Real* B() { return &mB; }
    Q_INVOKABLE Real* C() { return &mC; }

    Q_INVOKABLE void SetA(const Real* a) { mA = *a; }
    Q_INVOKABLE void SetB(const Real* b) { mB = *b; }
    Q_INVOKABLE void SetC(const Real* c) { mC = *c; }

private:
    Real mA;
    Real mB;
    Real mC;
};

//行程
class OBJLIB_EXPORT PointRun : public BaseData
{
    Q_OBJECT

    Q_PROPERTY(Integer* X READ X WRITE SetX)
    Q_PROPERTY(Integer* Y READ Y WRITE SetY)
    Q_PROPERTY(Integer* Length READ Length WRITE SetLength)
public:
    DATA_COPY_TYPE(PointRun)

    PointRun();
    PointRun(Integer x,Integer y,Integer length);
    PointRun(const PointRun& rhs);

    PointRun& operator = (const PointRun& rhs);

public:
    Q_INVOKABLE Integer* X() { return &mx; }
    Q_INVOKABLE Integer* Y() { return &my; }
    Q_INVOKABLE Integer* Length() { return &mLength; }

    Q_INVOKABLE void SetX(const Integer* x) { mx = *x; }
    Q_INVOKABLE void SetY(const Integer* y) { my = *y; }
    Q_INVOKABLE void SetLength(const Integer* length) { mLength = *length; }

private:
    Integer mx;
    Integer my;
    Integer mLength;
};

class OBJLIB_EXPORT Region : public BaseData
{
    Q_OBJECT

    Q_PROPERTY(Integer* FrameWidth READ FrameWidth WRITE SetFrameWidth)
    Q_PROPERTY(Integer* FrameHeight READ FrameHeight WRITE SetFrameHeight)
    Q_PROPERTY(Array* ArrayPointRun READ ArrayPointRun WRITE SetArrayPointRun)
public:
    DATA_COPY_TYPE(Region)

    Region();
    Region(const Region& rhs);
    ~Region();

    Region& operator = (const Region& rhs);

public:
    Q_INVOKABLE Integer* FrameWidth() { return &mFrameWidth; }
    Q_INVOKABLE Integer* FrameHeight() { return &mFrameHeight; }
    Q_INVOKABLE Array* ArrayPointRun() { return &mArrayPointRun; }

    Q_INVOKABLE void SetFrameWidth(const Integer* frameWidth) { mFrameWidth = *frameWidth; }
    Q_INVOKABLE void SetFrameHeight(const Integer* frameHeight) { mFrameHeight = *frameHeight; }

    Q_INVOKABLE void SetArrayPointRun(Array* array) { mArrayPointRun = *array; }

    Bool IsNull();//判断Region是否为空

    void Clear();//清空Region

private:
    Integer mFrameWidth;
    Integer mFrameHeight;
    Array mArrayPointRun{"PointRun"};
};

//路径或者链条
class OBJLIB_EXPORT Path : public BaseData
{
    Q_OBJECT

    Q_PROPERTY(Bool* Closed READ Closed WRITE SetClosed)
    Q_PROPERTY(Array* ArrayPoint READ ArrayPoint WRITE SetArrayPoint)
public:
    DATA_COPY_TYPE(Path)

    Path();
    Path(const Path& rhs);

    Path& operator = (const Path& rhs);

public:
    Bool* Closed() { return &mClosed; }
    void SetClosed(const Bool* closed) { mClosed = *closed; }

    Array* ArrayPoint() { return &mArrayPoint; }
    void SetArrayPoint(const Array* array) { mArrayPoint = *array; }

private:
    Bool mClosed;
    Array mArrayPoint{"Point2D"};
};

//路径或者链条
class OBJLIB_EXPORT PathFittingField : public BaseData
{
    Q_OBJECT

    Q_PROPERTY(Path* Axis READ Axis WRITE SetAxis)
    Q_PROPERTY(Real* Width READ Width WRITE SetWidth)
public:
    DATA_COPY_TYPE(PathFittingField)

    PathFittingField();
    PathFittingField(const PathFittingField& rhs);

    PathFittingField& operator = (const PathFittingField& rhs);

public:
    Q_INVOKABLE Path* Axis() { return &mAxis; }
    Q_INVOKABLE Real* Width() { return &mWidth; }

    Q_INVOKABLE void SetAxis(Path* axis) { mAxis = *axis; }
    Q_INVOKABLE void SetWidth(const Real* width) { mWidth = *width; }

private:
    Path mAxis;
    Real mWidth;
};

class OBJLIB_EXPORT PolarityType : public Enum
{
    Q_OBJECT
public:
    PolarityType()
    {
        AddEnumItem(0,"Bright");// 白
        AddEnumItem(1,"Dark");  // 黑
        AddEnumItem(2,"ANY");   // 任意
        SetKey(0);
    }
};

class OBJLIB_EXPORT Ridge1D : public BaseData
{
    Q_OBJECT
    DATA_COPY_TYPE(Ridge1D)

    Q_PROPERTY(Point2D* Point READ Point WRITE SetPoint)
    Q_PROPERTY(Real* Magnitude READ Magnitude WRITE SetMagnitude)
    Q_PROPERTY(PolarityType* Polarity READ Polarity WRITE SetPolarity)
public:
    Ridge1D();
    Ridge1D(const Point2D& point,Real magnitude,PolarityType polarity);
    Ridge1D(const Ridge1D& rhs);

    Ridge1D& operator = (const Ridge1D& rhs);

public:
    Q_INVOKABLE Point2D* Point() { return &mPoint; }
    Q_INVOKABLE Real* Magnitude() { return &mMagnitude; }
    Q_INVOKABLE PolarityType* Polarity() { return &mPolarity; }

    Q_INVOKABLE void SetPoint(Point2D* point) { mPoint = *point; }
    Q_INVOKABLE void SetMagnitude(const Real* magnitude) { mMagnitude = *magnitude; }
    Q_INVOKABLE void SetPolarity(const PolarityType* polarity) { mPolarity = *polarity; }

private:
    Point2D mPoint;
    Real mMagnitude;
    PolarityType mPolarity;
};

class OBJLIB_EXPORT Stripe1D : public BaseData
{
    Q_OBJECT
    DATA_COPY_TYPE(Stripe1D)

    Q_PROPERTY(Point2D* Point1 READ Point1 WRITE SetPoint1)
    Q_PROPERTY(Point2D* Point2 READ Point2 WRITE SetPoint2)
    Q_PROPERTY(Real* Width READ Width WRITE SetWidth)
    Q_PROPERTY(Real* Magnitude READ Magnitude WRITE SetMagnitude)
    Q_PROPERTY(PolarityType* Polarity READ Polarity WRITE SetPolarity)
public:
    Stripe1D();
    Stripe1D(const Point2D& point1,const Point2D& point2,Real width,Real magnitude,PolarityType polarity);
    Stripe1D(const Stripe1D& rhs);

    Stripe1D& operator = (const Stripe1D& rhs);

public:
    Q_INVOKABLE Point2D* Point1() { return &mPoint1; }
    Q_INVOKABLE Point2D* Point2() { return &mPoint2; }
    Q_INVOKABLE Real* Width() { return &mWidth; }
    Q_INVOKABLE Real* Magnitude() { return &mMagnitude; }
    Q_INVOKABLE PolarityType* Polarity() { return &mPolarity; }

    Q_INVOKABLE void SetPoint1(Point2D* point) { mPoint1 = *point; }
    Q_INVOKABLE void SetPoint2(Point2D* point) { mPoint2 = *point; }
    Q_INVOKABLE void SetWidth(const Real* width) { mWidth = *width; }
    Q_INVOKABLE void SetMagnitude(const Real* magnitude) { mMagnitude = *magnitude; }
    Q_INVOKABLE void SetPolarity(const PolarityType* polarity) { mPolarity = *polarity; }

private:
    Point2D mPoint1;
    Point2D mPoint2;
    Real mWidth;
    Real mMagnitude;
    PolarityType mPolarity;
};

//起点和终点决定一条有向线段
class OBJLIB_EXPORT Segment2D : public BaseData
{
    Q_OBJECT
    DATA_COPY_TYPE(Segment2D)

    Q_PROPERTY(Point2D* Point1 READ Point1 WRITE SetPoint1)
    Q_PROPERTY(Point2D* Point2 READ Point2 WRITE SetPoint2)
public:
    Segment2D();
    Segment2D(const Point2D& point1,const Point2D& point2);
    Segment2D(const Segment2D& rhs);

    Segment2D& operator = (const Segment2D& rhs);

public:
    Q_INVOKABLE Point2D* Point1() { return &mPoint1; }
    Q_INVOKABLE Point2D* Point2() { return &mPoint2; }

    Q_INVOKABLE void SetPoint1(Point2D* point) { mPoint1 = *point; }
    Q_INVOKABLE void SetPoint2(Point2D* point) { mPoint2 = *point; }

private:
    Point2D mPoint1;
    Point2D mPoint2;
};

//SegmentScanField //与SegmentFittingField取扫描线的方式不同
class OBJLIB_EXPORT SegmentFittingField : public BaseData
{
    Q_OBJECT
    DATA_COPY_TYPE(SegmentFittingField)

    Q_PROPERTY(Segment2D* Axis READ Axis WRITE SetAxis)
    Q_PROPERTY(Real* Width READ Width WRITE SetWidth)
public:
    SegmentFittingField();
    SegmentFittingField(const SegmentFittingField& rhs);

    SegmentFittingField& operator = (const SegmentFittingField& rhs);

public:
    Q_INVOKABLE Segment2D* Axis() { return &mAxis; }
    Q_INVOKABLE Real* Width() { return &mWidth; }

    Q_INVOKABLE void SetAxis(Segment2D* axis) { mAxis = *axis; }
    Q_INVOKABLE void SetWidth(const Real* width) { mWidth = *width; }

private:
    Segment2D mAxis;
    Real mWidth;
};

//坐标系
class OBJLIB_EXPORT CoordinateSystem2D : public BaseData
{
    Q_OBJECT

    Q_PROPERTY(Point2D* Origin READ Origin WRITE SetOrigin)
    Q_PROPERTY(Real* Angle READ Angle WRITE SetAngle)
    Q_PROPERTY(Real* Scale READ Scale WRITE SetScale)//Scale 必须大于0
    //Q_PROPERTY(Bool* IsNull READ IsNull)//坐标系是否为空 Scale<= 0 || Origin(0,0);Angle(0);Scale(1)
public:
    DATA_COPY_TYPE(CoordinateSystem2D)

    CoordinateSystem2D();
    CoordinateSystem2D(const Point2D& origin,Real angle,Real scale);
    CoordinateSystem2D(const CoordinateSystem2D& rhs);

    CoordinateSystem2D& operator = (const CoordinateSystem2D& rhs);

public:
    Point2D* Origin() { return &mOrigin; }
    Real* Angle() { return &mAngle; }
    Real* Scale() { return &mScale; }

    void SetOrigin(Point2D* origin) { mOrigin = *origin; }
    void SetAngle(const Real* angle) { mAngle = *angle; }
    void SetScale(const Real* scale) { mScale = *scale; }

    Bool IsNull();
    void Clear();

private:
    Point2D mOrigin;
    Real mAngle;
    Real mScale;
};

class OBJLIB_EXPORT Object2D : public BaseData
{
    Q_OBJECT

    Q_PROPERTY(Rectangle2D* Match READ Match WRITE SetMatch)
    Q_PROPERTY(CoordinateSystem2D* Alignment READ Alignment WRITE SetAlignment)
    Q_PROPERTY(Point2D* Point READ Point WRITE SetPoint)
    Q_PROPERTY(Real* Angle READ Angle WRITE SetAngle)
    Q_PROPERTY(Real* Scale READ Scale WRITE SetScale)
    Q_PROPERTY(Real* Score READ Score WRITE SetScore)
public:
    DATA_COPY_TYPE(Object2D)

    Object2D();
    Object2D(const Rectangle2D& match, const CoordinateSystem2D& alignment, const Point2D& point, Real angle, Real scale, Real score);
    Object2D(const Object2D& rhs);

    Object2D& operator = (const Object2D& rhs);

public:
    Q_INVOKABLE Rectangle2D* Match() { return &mMatch; }
    Q_INVOKABLE CoordinateSystem2D* Alignment() { return &mAlignment; }
    Q_INVOKABLE Point2D* Point() { return &mPoint; }
    Q_INVOKABLE Real* Angle() { return &mAngle; }
    Q_INVOKABLE Real* Scale() { return &mScale; }
    Q_INVOKABLE Real* Score() { return &mScore; }

    Q_INVOKABLE void SetMatch(Rectangle2D* match) { mMatch = *match; }
    Q_INVOKABLE void SetAlignment(CoordinateSystem2D* alignment) { mAlignment = *alignment; }
    Q_INVOKABLE void SetPoint(Point2D* point) { mPoint = *point; }
    Q_INVOKABLE void SetAngle(const Real* angle) { mAngle = *angle; }
    Q_INVOKABLE void SetScale(const Real* scale) { mScale = *scale; }
    Q_INVOKABLE void SetScore(const Real* score) { mScore = *score; }

private:
    Rectangle2D mMatch;     //一个矩形框
    CoordinateSystem2D mAlignment; //（即定义一个局部的参考坐标系，在模板匹配中是模板之间的相互变换）
    Point2D mPoint;     //目标在图像中的位置
    Real mAngle;     //angle和scale跟alignment中的值相同
    Real mScale;
    Real mScore;

    QVector<Path> mObjectEdges;//暂时没做 knq
};

class OBJLIB_EXPORT PlainType : public Enum
{
    Q_OBJECT
public:
    PlainType()
    {
        AddEnumItem(0,"Int8");
        AddEnumItem(1,"UInt8");
        AddEnumItem(2,"Int16");
        AddEnumItem(3,"UInt16");
        AddEnumItem(4,"Int32");
        AddEnumItem(5,"Real");
        SetKey(1);
    }
};

class ImageData : public QSharedData
{
public:
//    enum PlainType
//    {
//        Int8,
//        UInt8,
//        Int16,
//        UInt16,
//        Int32,
//        Real
//    };

    ImageData()
    {}

    ImageData(const ImageData& other)
        :QSharedData(other)
        ,width(other.width)
        ,height(other.height)
        ,type(other.type)
        ,depth(other.depth)
        ,pitch(other.pitch)
        ,data(other.data)
    {}

    ~ImageData()
    {}

    Integer width = 0;         //宽度 值为4的倍数
    Integer height = 0;        //高度
    PlainType type;
    Integer depth = 1;         //灰度=1
    Integer pitch = 0;          //行字节数lineBytes
    QByteArray data;
};

class OBJLIB_EXPORT Image : public BaseData
{
    Q_OBJECT

    Q_PROPERTY(Integer* Width READ Width WRITE SetWidth)
    Q_PROPERTY(Integer* Height READ Height WRITE SetHeight)
    Q_PROPERTY(Integer* Pitch READ Pitch)
    Q_PROPERTY(Integer* Depth READ Depth WRITE SetDepth)
    Q_PROPERTY(PlainType* Type READ Type WRITE SetType)
    Q_PROPERTY(Integer* PixelSize READ PixelSize)
public:
    DATA_COPY_TYPE(Image)

    Image();

    Image(Integer width, Integer height, PlainType type, Integer depth, Integer pitch, uchar* data);

    Image(Integer width, Integer height, PlainType type, Integer depth, const uchar* data);

    Image(const Image& other);

    ~Image();

    Image operator=(const Image& other);//浅拷贝

    void Assign(BaseData* const rhs)
    {
        *this = *qobject_cast<Image*>(rhs);
    }

public:
    QString DebugString(bool complete = false) override;

public:
    void SetWidth(Integer* width)
    {
        d_ptr->width = *width;
    }
    void SetHeight(Integer* height)
    {
        d_ptr->height = *height;
    }
    void SetType(PlainType* type)
    {
        d_ptr->type = *type;
    }
    void SetDepth(Integer* depth)
    {
        d_ptr->depth = *depth;
    }
    void SetData(int idx, int value)
    {
        d_ptr->data[idx] = value;
    }

    Integer* Width()
    {
        return &d_ptr->width;
    }
    Integer* Height()
    {
        return &d_ptr->height;
    }
    PlainType* Type()
    {
        return &d_ptr->type;
    }
    Integer* Depth()
    {
        return &d_ptr->depth;
    }
    uchar* Bits()
    {
        return (uchar*)d_ptr->data.data();
    }

    const uchar* ConstBits() const
    {
        return (const uchar*)d_ptr->data.data();
    }

    Integer* Pitch();

    Integer* PixelSize();

    void Reset(int newWidth, int newHeight, PlainType newType, int newDepth);

    static int Pitch(PlainType type,int depth,int width,int pitchAlignment);

    static int sizeof_PlainType(PlainType type );

private:
    QSharedDataPointer<ImageData> d_ptr;
    Integer pixelsize;
};

}

Q_DECLARE_METATYPE(xvs::Integer)
Q_DECLARE_METATYPE(xvs::Real)
Q_DECLARE_METATYPE(xvs::String)
Q_DECLARE_METATYPE(xvs::Bool)
Q_DECLARE_METATYPE(xvs::Array)

Q_DECLARE_METATYPE(xvs::Point2DInt)
Q_DECLARE_METATYPE(xvs::Point2D)
Q_DECLARE_METATYPE(xvs::Point3D)
Q_DECLARE_METATYPE(xvs::Circle2D)
Q_DECLARE_METATYPE(xvs::CircleFittingField)
Q_DECLARE_METATYPE(xvs::Arc2D)
Q_DECLARE_METATYPE(xvs::ArcFittingField)
Q_DECLARE_METATYPE(xvs::Rectangle2D)
Q_DECLARE_METATYPE(xvs::Rectangle2DInt)
Q_DECLARE_METATYPE(xvs::Box2D)
Q_DECLARE_METATYPE(xvs::Box2DInt)
Q_DECLARE_METATYPE(xvs::EdgeTransitionType)
Q_DECLARE_METATYPE(xvs::Edge1D)
Q_DECLARE_METATYPE(xvs::Gap1D)
Q_DECLARE_METATYPE(xvs::Line2D)
Q_DECLARE_METATYPE(xvs::PointRun)
Q_DECLARE_METATYPE(xvs::Region)
Q_DECLARE_METATYPE(xvs::Path)
Q_DECLARE_METATYPE(xvs::PathFittingField)
Q_DECLARE_METATYPE(xvs::PolarityType)
Q_DECLARE_METATYPE(xvs::Ridge1D)
Q_DECLARE_METATYPE(xvs::Stripe1D)
Q_DECLARE_METATYPE(xvs::Segment2D)
Q_DECLARE_METATYPE(xvs::SegmentFittingField)
Q_DECLARE_METATYPE(xvs::CoordinateSystem2D)
Q_DECLARE_METATYPE(xvs::Object2D)
Q_DECLARE_METATYPE(xvs::ImageData)
Q_DECLARE_METATYPE(xvs::Image)

#endif // BASEDATA_H
